home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / srcuc.zip / WIND.C < prev    next >
C/C++ Source or Header  |  1991-07-06  |  6KB  |  197 lines

  1. /* Copyright (C) 1990-91 Free Software Foundation, Inc.
  2.  
  3.    This program is free software; you can redistribute it and/or modify
  4.    it under the terms of the GNU General Public License as published by
  5.    the Free Software Foundation; either version 1, or (at your option)
  6.    any later version.
  7.  
  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.
  12.  
  13.    You should have received a copy of the GNU General Public License
  14.    along with this program; if not, write to the Free Software
  15.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  16.  
  17. /* $Header: /scheme/microcode/RCS/wind.c,v 1.4 1991/07/06 21:42:41 cph Exp $ */
  18.  
  19. #include <stdio.h>
  20. #include "obstack.h"
  21. #include "dstack.h"
  22. extern void EXFUN (free, (PTR ptr));
  23. #define obstack_chunk_alloc xmalloc
  24. #define obstack_chunk_free free
  25.  
  26. extern void EXFUN (block_signals, (void));
  27. extern void EXFUN (unblock_signals, (void));
  28.  
  29. static void
  30. DEFUN (error, (procedure_name, message),
  31.        CONST char * procedure_name AND
  32.        CONST char * message)
  33. {
  34.   fprintf (stderr, "%s: %s\n", procedure_name, message);
  35.   fflush (stderr);
  36.   abort ();
  37. }
  38.  
  39. static PTR
  40. DEFUN (xmalloc, (length), unsigned int length)
  41. {
  42.   extern PTR EXFUN (malloc, (unsigned int length));
  43.   PTR result = (malloc (length));
  44.   if (result == 0)
  45.     error ("malloc", "memory allocation failed");
  46.   return (result);
  47. }
  48.  
  49. struct winding_record
  50. {
  51.   struct winding_record * next;
  52.   void EXFUN ((*protector), (PTR environment));
  53.   PTR environment;
  54. };
  55.  
  56. static struct obstack dstack;
  57. static struct winding_record * current_winding_record;
  58. PTR dstack_position;
  59.  
  60. void
  61. DEFUN_VOID (dstack_initialize)
  62. {
  63.   obstack_init (&dstack);
  64.   dstack_position = 0;
  65.   current_winding_record = 0;
  66. }
  67.  
  68. void
  69. DEFUN_VOID (dstack_reset)
  70. {
  71.   block_signals ();
  72.   obstack_free ((&dstack), 0);
  73.   dstack_initialize ();
  74.   unblock_signals ();
  75. }
  76.  
  77. #define EXPORT(sp) ((PTR) (((char *) (sp)) + (sizeof (PTR))))
  78.  
  79. PTR
  80. DEFUN (dstack_alloc, (length), unsigned int length)
  81. {
  82.   PTR chunk;
  83.   block_signals ();
  84.   chunk = (obstack_alloc ((&dstack), ((sizeof (PTR)) + length)));
  85.   (* ((PTR *) chunk)) = dstack_position;
  86.   dstack_position = chunk;
  87.   unblock_signals ();
  88.   return (EXPORT (chunk));
  89. }
  90.  
  91. void
  92. DEFUN (dstack_protect, (protector, environment),
  93.        void EXFUN ((*protector), (PTR environment)) AND
  94.        PTR environment)
  95. {
  96.   struct winding_record * record =
  97.     (dstack_alloc (sizeof (struct winding_record)));
  98.   (record -> next) = current_winding_record;
  99.   (record -> protector) = protector;
  100.   (record -> environment) = environment;
  101.   current_winding_record = record;
  102. }
  103.  
  104. void
  105. DEFUN (dstack_alloc_and_protect, (length, initializer, protector),
  106.        unsigned int length AND
  107.        void EXFUN ((*initializer), (PTR environment)) AND
  108.        void EXFUN ((*protector), (PTR environment)))
  109. {
  110.   struct winding_record * record =
  111.     (dstack_alloc ((sizeof (struct winding_record)) + length));
  112.   PTR environment = (((char *) record) + (sizeof (struct winding_record)));
  113.   (*initializer) (environment);
  114.   (record -> next) = current_winding_record;
  115.   (record -> protector) = protector;
  116.   (record -> environment) = environment;
  117.   current_winding_record = record;
  118. }
  119.  
  120. void
  121. DEFUN (dstack_set_position, (position), PTR position)
  122. {
  123.   block_signals ();
  124. #define DEBUG_DSTACK
  125. #ifdef DEBUG_DSTACK
  126.   {
  127.     PTR * sp = dstack_position;
  128.     while (sp != position)
  129.       {
  130.     if (sp == 0)
  131.       error ("dstack_set_position", "position argument not found");
  132.     sp = (*sp);
  133.       }
  134.   }
  135. #endif /* DEBUG_DSTACK */
  136.   while (dstack_position != position)
  137.     {
  138.       if (dstack_position == 0)
  139.     error ("dstack_set_position", "no more stack");
  140.       if ((EXPORT (dstack_position)) == current_winding_record)
  141.     {
  142.       PTR sp = dstack_position;
  143.       struct winding_record * record = current_winding_record;
  144.       /* Must unblock signals while the protector runs, and
  145.          re-block afterwards, in case the protector does something
  146.          to change the signal mask.  Otherwise, the change to the
  147.          signal mask will be undone when the final call to
  148.          unblock_signals is performed.  */
  149.       unblock_signals ();
  150.       (* (record -> protector)) (record -> environment);
  151.       block_signals ();
  152.       if (sp != dstack_position)
  153.         error ("dstack_set_position", "stack slipped during unwind");
  154.       current_winding_record = (record -> next);
  155.     }
  156.       {
  157.     PTR * sp = dstack_position;
  158.     dstack_position = (*sp);
  159.     obstack_free ((&dstack), sp);
  160.       }
  161.     }
  162.   unblock_signals ();
  163. }
  164.  
  165. struct binding_record
  166. {
  167.   PTR * location;
  168.   PTR value;
  169. };
  170.  
  171. static void
  172. DEFUN (undo_binding, (environment), PTR environment)
  173. {
  174.   (* (((struct binding_record *) environment) -> location)) =
  175.     (((struct binding_record *) environment) -> value);
  176. }
  177.  
  178. static PTR * save_binding_location;
  179.  
  180. static void
  181. DEFUN (save_binding, (environment), PTR environment)
  182. {
  183.   (((struct binding_record *) environment) -> location) =
  184.     save_binding_location;
  185.   (((struct binding_record *) environment) -> value) =
  186.     (*save_binding_location);
  187. }
  188.  
  189. void
  190. DEFUN (dstack_bind, (location, value), PTR location AND PTR value)
  191. {
  192.   save_binding_location = location;
  193.   dstack_alloc_and_protect
  194.     ((sizeof (struct binding_record)), save_binding, undo_binding);
  195.   (* ((PTR *) location)) = value;
  196. }
  197.